#include "ai_instant.h"
#include "ui_ai_instant.h"


extern int trainTime;

double xLength;
double xV;
double xD;

#include <QTimer>
#include <QMessageBox>
#include <math.h>
#include <QDir>
#include <QTextStream>
#include <QDateTime>
#include "numeric"
Ai_Instant::Ai_Instant(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Ai_Instant)
{
    ui->setupUi(this);
    this->setWindowFlag(Qt::FramelessWindowHint);

    // Initialize the scaled data array.
    //初始化数据组
    memset(scaledData,0,sizeof (scaledData));
    instantAiCtrl = nullptr;
    OriTrainTime = trainTime;
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(TimerTicked()));
    graph = new SimpleGraph(ui->graphFrame);
    graph->setFixedSize(ui->graphFrame->size());
    ui->time_lcd->display(trainTime);
    ui->time_progressBar->setMaximum(trainTime);
    ui->time_progressBar->setValue(0);
    LCDtimer = new QTimer(this);
    connect(LCDtimer,SIGNAL(timeout()),this,SLOT(slot_LCDTimeOut()));
    ui->move_lineEdit->move(ui->moveSlider->x() + (ui->moveSlider->width() - ui->move_lineEdit->width()) / 2,
                            ui->moveSlider->y() - ui->move_lineEdit->height());
    OriX = ui->move_lineEdit->x();


    dampingTimer = new QTimer(this);
    connect(dampingTimer, SIGNAL(timeout()), this, SLOT(slot_dampingTimeOut()));


    ui->report_toolButton->setEnabled(false);


}

void Ai_Instant::slot_LCDTimeOut(){
    if(trainTime <= 0){
        timer->stop();
        LCDtimer->stop();
        trainTime = OriTrainTime;
        ui->time_lcd->display(0);
        countX(xVector);
        QVector<double>().swap(xVector);
        ui->time_progressBar->setValue(0);
        graph->Clear();
        ui->progressBar_left->setValue(0);
        ui->progressBar_right->setValue(0);
        ui->btnStart->setText(tr("重来"));
        ui->btnPause->setEnabled(false);
        ui->btnStart->setEnabled(true);
        ui->btnStop->setEnabled(false);
    }
    else{
        trainTime--;
//        QString s = QString::number(trainTime);
        ui->time_lcd->display(trainTime);
        ui->time_progressBar->setValue(trainTime);
    }
}

Ai_Instant::~Ai_Instant()
{
    trainTime = OriTrainTime;
    instantAiCtrl->Dispose();
    delete ui;
}

//执行定时器槽函数
void Ai_Instant::TimerTicked()
{
    ErrorCode errorCode = Success;
        //关键：从instanAiCtrl中读取scaledData
     errorCode = instantAiCtrl->Read(configure.channelStart, configure.channelCount, scaledData);
     CheckError(errorCode);
     if (errorCode != Success)
     {
        return;
     }

     //配置控件数据
     int dataCylic = ui->sldTimerValue->value();
     graph->Chart(scaledData, configure.channelCount, 1, 1.0 * dataCylic / 1000);
     //更新数据
     RefreshList();
}

void Ai_Instant::CheckError(ErrorCode errorCode)
{
   if (BioFailed(errorCode))
   {
        QString message = tr("发生错误, 错误代码: 0x") +
            QString::number(errorCode, 16).right(8).toUpper();
        QMessageBox::information(this, "警告", message);
    }
}

double Ai_Instant::Round(double dVal, int iPlaces)
{
    double dRetval;
    double dMod = 0.0000001;
    if (dVal < 0.0) dMod = -0.0000001;
    dRetval = dVal;
    dRetval += (5.0 / pow(10.0,iPlaces + 1.0));
    dRetval *= pow(10.0,iPlaces);
    dRetval = floor(dRetval + dMod);
    dRetval /= pow(10.0,iPlaces);
    return(dRetval);
}

double Ai_Instant::ValueToWeight_0(double value){
    //通道0拟合公式：y = 33.776x + 0.6267  R² = 0.9988
    QString s = "y = 33.776x + 0.6267\nR² = 0.9988";
    if(value <= 0.03) return 0;
    else return (34.776 * value + 0.6267  );
}

double Ai_Instant::ValueToWeight_1(double value){
    //通道1拟合公式： y = 27.093x - 4.9302    R² = 0.9999  4.9302 / 27.093 = 0.182
    QString s = "y = 27.093x - 4.9302\nR² = 0.9999";
    if(value <= 0.3) return 0;
    else return (28.093 * value - 4.9302 + 0.1);//补偿0.1
}



void Ai_Instant::RefreshList()//重要函数———获取数据并显示出来，更新
{
    //显示电压值，4位小数
    QString value_0 = tr("0.0000");
    QString value_1 = tr("0.0000");


    //电压值保留4位小数
    value_0.sprintf("%.4f",scaledData[0]);
    value_1.sprintf("%.4f",scaledData[1]);

    //显示电压值
//    ui->left_Vlabel->setText(value_0);
//    ui->right_Vlabel->setText(value_1);

    //显示重量值，1位小数
    double leftW = Round(ValueToWeight_0(value_0.toDouble()),1);
    double rightW = Round(ValueToWeight_1(value_1.toDouble()),1);


    ui->left_Wlabel->setText(QString::number(leftW));
    ui->right_Wlabel->setText(QString::number(rightW));
    ui->whole_Wlabel->setText(QString::number(leftW + rightW));

    //显示偏移百分比，1位小数
    double leftPer = 0.0;
    double rightPer = 0.0;
    if(leftW == 0 && rightW == 0) {
        leftPer = 0;
        rightPer = 0;
    }
    else {
        leftPer = Round(leftW / (leftW + rightW) * 100,1);
        rightPer = Round(rightW / (leftW + rightW) * 100,1);
    }
    ui->letfPer_label->setText(QString::number(leftPer) + "%");
    ui->rightPer_label->setText(QString::number(rightPer) + "%");


    //显示进度条变化
    leftW >= 50 ? ui->progressBar_left->setValue(50) : ui->progressBar_left->setValue(leftW);
    rightW >= 50 ? ui->progressBar_right->setValue(50) : ui->progressBar_right->setValue(rightW);

    /**
      显示坐标变化
      **/
    //获取两压力板之间的距离
    QString dString = ui->distancelineEdit->text();
    double d = 10 * dString.toDouble();//单位：mm
    //设置数轴的范围并显示
    ui->moveSlider->setMinimum(-(d / 2));
    ui->moveSlider->setMaximum(d / 2);
    ui->moveMin_label->setText(QString::number(-(d / 2)));
    ui->moveMax_label->setText(QString::number(d / 2));
    //计算坐标的值：
    double x = 0.0;
    if(leftW == 0 && rightW == 0) x = 0;
    else x = d * (rightW - leftW) / (2 * (leftW + rightW));
    ui->moveSlider->setValue(x);
    ui->move_lineEdit->setText(QString::number(Round(x,1)));
    ui->move_lineEdit->move(OriX + ui->moveSlider->width() * x / d,ui->move_lineEdit->y());

    //根据阻尼因子计算坐标的值
//    ui->move_lineEdit_2->move(OriX + ui->moveSlider->width() * x / d * DAMPING,ui->move_lineEdit->y() + 100);
//    ui->move_lineEdit_2->setText(QString::number(Round((x * DAMPING),1)));

}

void Ai_Instant::Initialize()//初始化
{
    ConfigureDevice();//配置设备
    ConfigureGraph();//配置图表

    //Initialize the list.初始化通道颜色列表
    ui->btnStart->setEnabled(true);
    ui->btnPause->setEnabled(false);
    ui->btnStop->setEnabled(false);
    ui->sldTimerValue->setEnabled(true);

}

void Ai_Instant::ConfigureDevice()//配置设备
{
    if (instantAiCtrl == nullptr)
    {
      instantAiCtrl = InstantAiCtrl::Create();
    }

    //获取所选择的设备名称及其属性
    std::wstring description = configure.deviceName.toStdWString();
    DeviceInformation selected(description.c_str());

    //instantAiCtrl->setSelectedDevice(selected);获取控制码
    ErrorCode errorCode = instantAiCtrl->setSelectedDevice(selected);
    CheckError(errorCode);
    errorCode = instantAiCtrl->LoadProfile(configure.profilePath);
    CheckError(errorCode);

    //Get channel max number. set value range for every channel.
    //获取通道数，设置每个通道的取值范围
    Array<AiChannel> *channels = instantAiCtrl->getChannels();
    for (int i = 0; i < channels->getCount(); i++)
    {
        channels->getItem(i).setValueRange(configure.valueRange);
    }
}

void Ai_Instant::ConfigureGraph()
{
    TimeUnit timeUnit = Second;
    QString	xRanges[2] = {tr("")};
    graph->GetXCordRange(xRanges, 10, 0, timeUnit);
    ui->lblXCoordinateStart->setText(xRanges[1]);
    ui->lblXCoordinateEnd->setText(xRanges[0]);

    ValueUnit unit;
    MathInterval rangeY;
    QString yRanges[3] = {tr("")};
    ErrorCode errorCode = AdxGetValueRangeInformation(configure.valueRange, 0, nullptr, &rangeY, &unit);
    CheckError(errorCode);

    graph->GetYCordRange(yRanges, rangeY.Max, rangeY.Min, unit);
    ui->lblYCoordinateMax->setText(yRanges[0]);
    ui->lblYCoordinateMin->setText(yRanges[1]);
    ui->lblYCoordinateMid->setText(yRanges[2]);

    if (Milliampere == unit || Millivolt == unit)
    {
        rangeY.Max /= 1000;
        rangeY.Min /= 1000;
    }
    graph->m_xCordTimeDiv = 1000;
    graph->m_yCordRangeMax = rangeY.Max;
    graph->m_yCordRangeMin = rangeY.Min;
    graph->Clear();
}

//void Ai_Instant::on_btnConfigure_clicked()
//{
//    timer->stop();
//    graph->Clear();

//    int dialogResult = configDialog->exec();
//    if (dialogResult == QDialog::Accepted)
//    {
//        configure = configDialog->GetConfigureParameter();
//        Initialize();
//    }
//}

void Ai_Instant::on_btnStart_clicked()
{
    ui->report_toolButton->setEnabled(false);
    int dataCylic = ui->sldTimerValue->value();
    timer->start(dataCylic);
    LCDtimer->start(1000);
    ui->btnStart->setEnabled(false);
    ui->btnPause->setEnabled(true);
    ui->btnStop->setEnabled(true);
}

void Ai_Instant::on_btnPause_clicked()
{
    //停止定时器
    timer->stop();
    LCDtimer->stop();
    ui->btnPause->setEnabled(false);
    ui->btnStart->setEnabled(true);
    ui->btnStart->setText(tr("继续"));
    ui->btnStop->setEnabled(true);
}

void Ai_Instant::on_btnStop_clicked()
{
    timer->stop();
    LCDtimer->stop();
    trainTime = OriTrainTime;
//    ui->time_lcd->display(0);
    ui->time_progressBar->setValue(0);
    graph->Clear();
    ui->progressBar_left->setValue(0);
    ui->progressBar_right->setValue(0);
    ui->btnPause->setEnabled(false);
    ui->btnStart->setEnabled(true);
    ui->btnStart->setText(tr("重来"));
    ui->btnStop->setEnabled(false);
    countX(xVector);
    ui->report_toolButton->setEnabled(true);
    QVector<double>().swap(xVector);
}

void Ai_Instant::on_sldTimerValue_valueChanged(int value)
{
    ui->edtTimeValue->setText(QString("%1").arg(value));
    timer->setInterval(ui->sldTimerValue->value());//设置采样频率为时间间隔
    graph->Clear();
}

void Ai_Instant::on_edtTimeValue_returnPressed()
{
    int value = ui->edtTimeValue->text().toInt();
    ui->sldTimerValue->setValue(value);
    timer->setInterval(value);
    graph->Clear();
}

void Ai_Instant::on_btnBack_clicked()
{
    //停止定时器
    timer->stop();
    LCDtimer->stop();
    countX(xVector);
    QVector<double>().swap(xVector);
    instantAiCtrl->Dispose();
    this->close();
}

void Ai_Instant::slot_dampingTimeOut(){

}



void Ai_Instant::on_move_lineEdit_textChanged(const QString &arg1)
{

    xVector.append(arg1.toDouble());

}

void Ai_Instant::countX(QVector<double> x){
    int t = OriTrainTime - ui->time_lcd->value();
    xLength = 0;
    for (int i = 0;i < x.size() - 1;i++) {//不够严谨
        xLength += qAbs(x[i] - x[i+1]);
    }
    xV = xLength / t;
    double xDSum = 0;
    for (int i = 0;i < x.size() - 1;i++) {//不够严谨
        xDSum += x[i];
    }
    xD = xDSum / x.size();

}


void Ai_Instant::on_report_toolButton_clicked()
{
    Report *report = new Report();
    report->show();
}
